package com.bsg.upm.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bsg.upm.check.CheckResult;
import com.bsg.upm.check.ServDirectUserCheck;
import com.bsg.upm.constant.OperateDictConstants;
import com.bsg.upm.constant.OperateDictTypeConstants;
import com.bsg.upm.constant.SysConstants;
import com.bsg.upm.dto.ServDirectUserDto;
import com.bsg.upm.entity.ServEntity;
import com.bsg.upm.entity.SubServEntity;
import com.bsg.upm.exception.APIException;
import com.bsg.upm.http.RespJson;
import com.bsg.upm.http.RespJsonFactory;

/**
 * 直连用户管理业务处理类
 * 
 * @author HCK
 *
 */
@Service
public class ServDirectUserService extends BaseService {

	@Resource
	private ServDirectUserCheck servDirectUserCheck;

	/**
	 * 直连用户查询
	 * 
	 * @param servId
	 *            服务编码
	 * @return 操作结果
	 * @throws APIException
	 *             API异常处理类
	 */
	public RespJson list(String servId) throws APIException {
		try {
			// 结果集
			JSONArray results = new JSONArray();

			// 获取指定服务
			ServEntity serv = servDao.getBase(servId);
			if (serv == null) {
				return RespJsonFactory.build(HttpStatus.SC_GONE, "服务不存在");
			}

			if (!SysConstants.SERV_UPSQL_UPPROXY_SWM_CODE.equals(serv.getOrder().getDefinitionServ().getCode())) {
				return RespJsonFactory.build(HttpStatus.SC_BAD_REQUEST, "该类型服务无直连用户");
			}

			// 获取主单元关联名称
			Map<String, String> masterMap = getMasterUnitRelateName(serv);

			// 判断是否存在主单元
			boolean existMasterUnit = existMaster(masterMap);
			if (!existMasterUnit) {
				throw new APIException("获取不到主单元");
			}

			// 站点
			String siteId = serv.getOrder().getArea().getSite().getId();

			// 子服务
			List<SubServEntity> subServs = serv.getSubServs();
			for (SubServEntity subServ : subServs) {
				// 单元关联名称
				String unitRelateName = masterMap.get(subServ.getRelateId());
				if (StringUtils.isNotBlank(unitRelateName)) {
					// 构建执行查询直连用户接口参数
					String param = buildParamForExecList(unitRelateName, serv);

					// 从MGM获取直连用户信息
					String userInfo = executeMgmExec(siteId, subServ.getRelateId(), param);
					if (StringUtils.isNotBlank(userInfo)) {
						String[] userInfoArr = userInfo.split("\\n");
						for (int i = 0; i < userInfoArr.length; i++) {
							if (StringUtils.isNotBlank(userInfoArr[i])) {
								String[] arr = userInfoArr[i].split("::");
								if (arr.length == 4) {
									ServDirectUserDto userDto = new ServDirectUserDto();
									userDto.setUsername(arr[0]);
									if (StringUtils.isNotBlank(arr[1])) {
										userDto.setIps(Arrays.asList(arr[1].replaceAll(" ", "").split(",")));
									}
									userDto.setDatabaseName(arr[2]);
									if (StringUtils.isNotBlank(arr[3])) {
										userDto.setPrivileges(Arrays.asList(arr[3].replaceAll(" ", "").split(",")));
									}
									results.add(userDto);
								}
							}
						}
					}
					break;
				}
			}
			return RespJsonFactory.buildOK(results);
		} catch (Exception e) {
			logger.error("直连用户查询异常", e);
			throw new APIException("直连用户查询异常:" + e.getMessage());
		}
	}

	/**
	 * 直连用户新增
	 * 
	 * @param paramMap
	 *            请求参数
	 * @return RespJson请求结果对象
	 * @throws APIException
	 *             API异常处理类
	 */
	@Transactional(rollbackFor = APIException.class)
	public RespJson save(Map<String, Object> paramMap) throws APIException {
		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_ADD;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// 新增检查
			CheckResult chkRS = servDirectUserCheck.checkSave(paramMap);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			String servId = (String) paramMap.get("servId");

			// 获取指定的服务
			ServEntity serv = servDao.getBase(servId);

			// 获取主单元关联名称
			Map<String, String> masterMap = getMasterUnitRelateName(serv);
			for (Map.Entry<String, String> entry : masterMap.entrySet()) {
				if (StringUtils.isBlank(entry.getValue())) {
					throw new APIException("存在分片没有主单元");
				}
			}

			// 站点
			String siteId = serv.getOrder().getArea().getSite().getId();
			List<SubServEntity> subServs = serv.getSubServs();
			for (SubServEntity subServ : subServs) {
				if (StringUtils.isNotBlank(masterMap.get(subServ.getRelateId()))) {
					// 构建执行新增直连用户接口参数
					String param = buildParamForExecAdd(masterMap.get(subServ.getRelateId()), paramMap);

					// 向MGM新增直连用户信息
					executeMgmExec(siteId, subServ.getRelateId(), param);
				}
			}

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_SERV_DIRECT_USER, operateAcion, (String) paramMap.get("username"),
					(String) paramMap.get("username"));

			return RespJsonFactory.buildCreated();
		} catch (Exception e) {
			logger.error("直连用户" + operateAcionText + "异常", e);
			throw new APIException("直连用户" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 直连用户删除
	 * 
	 * @param servId
	 *            服务编码
	 * @param username
	 *            用户名
	 * @param ip
	 *            ip地址
	 * @return 操作结果
	 * @throws APIException
	 *             API异常处理类
	 */
	@Transactional(rollbackFor = APIException.class)
	public RespJson remove(String servId, String username, String ip) throws APIException {
		// 操作动作
		String operateAcion = OperateDictConstants.ACTION_REMOVE;
		String operateAcionText = dictTypeCache.getTextFromCache(OperateDictTypeConstants.OPERATE_ACTION, operateAcion);
		try {
			// 获取指定服务
			ServEntity serv = servDao.getBase(servId);

			// 删除检查
			CheckResult chkRS = servDirectUserCheck.checkRemove(serv);
			if (chkRS.isError()) {
				return RespJsonFactory.build(chkRS.getStatus(), chkRS.getErrorMsg());
			}

			// 获取主单元关联名称
			Map<String, String> masterMap = getMasterUnitRelateName(serv);
			for (Map.Entry<String, String> entry : masterMap.entrySet()) {
				if (StringUtils.isBlank(entry.getValue())) {
					throw new APIException("存在分片没有主单元");
				}
			}

			String siteId = serv.getOrder().getArea().getSite().getId();
			List<SubServEntity> subServs = serv.getSubServs();
			for (SubServEntity subServ : subServs) {
				if (StringUtils.isNotBlank(masterMap.get(subServ.getRelateId()))) {
					// 构建执行删除直连用户接口参数
					String param = buildParamForExecDelete(masterMap.get(subServ.getRelateId()), username, ip);

					// 从MGM删除直连用户信息
					executeMgmExec(siteId, subServ.getRelateId(), param);
				}
			}

			// 保存操作日志
			saveOperateLog(OperateDictConstants.MODEL_SERV_DIRECT_USER, operateAcion, username, username);

			return RespJsonFactory.buildNoContent();
		} catch (Exception e) {
			logger.error("直连用户" + operateAcionText + "异常", e);
			throw new APIException("直连用户" + operateAcionText + "异常" + e.getMessage());
		}
	}

	/**
	 * 构建执行exec list接口参数
	 * 
	 * @param masterMgmUnit
	 *            mgm单元编码/名称
	 * @param serv
	 *            服务对象
	 * @return exec接口参数
	 */
	private String buildParamForExecList(String masterMgmUnit, ServEntity serv) throws APIException {
		JSONObject paramJson = new JSONObject();
		paramJson.put("nameOrID", masterMgmUnit);

		JSONArray cmdJsonArr = new JSONArray();
		paramJson.put("cmd", cmdJsonArr);

		cmdJsonArr.add("/root/user_mgm.sh");
		cmdJsonArr.add("list");
		cmdJsonArr.add("exclude");

		List<String> ips = new ArrayList<>();

		// 站点
		String siteId = serv.getOrder().getArea().getSite().getId();

		// 服务类型
		String servType = serv.getOrder().getDefinitionServ().getName();
		List<SubServEntity> subServs = serv.getSubServs();
		for (SubServEntity subServ : subServs) {
			// 子服务类型
			String dfServType = subServ.getSubOrder().getDefinitionSubServ().getName();
			if (SysConstants.SERV_UPSQL_UPPROXY_SWM_CODE.equals(servType)
					&& (SysConstants.SUBSERV_SWM_NAME.equals(dfServType)
							|| SysConstants.SUBSERV_UPPROXY_NAME.equals(dfServType))) {
				if (StringUtils.isNotBlank(subServ.getRelateId())) {
					List<Map<String, Object>> ipAndPorts = listIpAndPortFromMGM(siteId, subServ.getRelateId(),
							subServ.getSubOrder().getDefinitionSubServ().getPortKey());
					for (Map<String, Object> map : ipAndPorts) {
						ips.add((String) map.get("ip"));
					}
				}
			}
		}
		cmdJsonArr.add(StringUtils.join(ips.toArray(), ","));
		return paramJson.toJSONString();
	}

	/**
	 * 构建执行exec add接口参数
	 * 
	 * @param masterMgmUnit
	 *            mgm单元编码/名称
	 * @param paramMap
	 *            请求参数
	 * @return exec接口参数
	 */
	@SuppressWarnings("unchecked")
	private String buildParamForExecAdd(String masterMgmUnit, Map<String, Object> paramMap) throws APIException {
		JSONObject paramJson = new JSONObject();
		paramJson.put("nameOrID", masterMgmUnit);

		JSONArray cmdJsonArr = new JSONArray();
		paramJson.put("cmd", cmdJsonArr);

		cmdJsonArr.add("/root/user_mgm.sh");
		cmdJsonArr.add("add");
		cmdJsonArr.add((String) paramMap.get("username"));
		List<String> ips = (List<String>) paramMap.get("ips");
		cmdJsonArr.add(StringUtils.join(ips.toArray(), ","));
		cmdJsonArr.add((String) paramMap.get("databaseName"));
		List<String> privileges = (List<String>) paramMap.get("privileges");
		cmdJsonArr.add(StringUtils.join(privileges.toArray(), ","));
		cmdJsonArr.add((String) paramMap.get("password"));

		return paramJson.toJSONString();
	}

	/**
	 * 构建执行exec add接口参数
	 * 
	 * @param masterMgmUnit
	 *            mgm单元编码/名称
	 * @param username
	 *            用户名
	 * @param ip
	 *            ip地址
	 * @return exec接口参数
	 */
	private String buildParamForExecDelete(String masterMgmUnit, String username, String ip) throws APIException {
		JSONObject paramJson = new JSONObject();
		paramJson.put("nameOrID", masterMgmUnit);

		JSONArray cmdJsonArr = new JSONArray();
		paramJson.put("cmd", cmdJsonArr);

		cmdJsonArr.add("/root/user_mgm.sh");
		cmdJsonArr.add("delete");
		cmdJsonArr.add(username);
		cmdJsonArr.add(ip);

		return paramJson.toJSONString();
	}

}
